{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9d0783fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2.5.1+cu124\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "print(torch.__version__)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "5fc5a201",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SCALAR: tensor(7)\n",
      "SCALAR.ndim: 0\n"
     ]
    }
   ],
   "source": [
    "SCALAR = torch.tensor(7)\n",
    "print(\"SCALAR:\", SCALAR)\n",
    "print(\"SCALAR.ndim:\", SCALAR.ndim)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4249346b",
   "metadata": {},
   "source": [
    "1. 获取 张量最外维度的大小 `scalar.item()`\n",
    "1. 获取 张量的形状 `scalar.shape`\n",
    "1. 获取 张量有多少交叉信息种类 `SCALAR.ndim`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "eac1f4f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SCALAR.item(): 7\n",
      "SCALAR.shape: torch.Size([])\n"
     ]
    }
   ],
   "source": [
    "print(\"SCALAR.item():\", SCALAR.item())\n",
    "print(\"SCALAR.shape:\", SCALAR.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "05936515",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "tensor([7, 7])\n",
      "VECTOR.ndim: 1\n",
      "VECTOR.shape: torch.Size([2])\n"
     ]
    }
   ],
   "source": [
    "VECTOR = torch.tensor([7, 7])\n",
    "print(\"------------------------------------\")\n",
    "print(VECTOR)\n",
    "print(\"VECTOR.ndim:\", VECTOR.ndim)\n",
    "print(\"VECTOR.shape:\", VECTOR.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "172234a5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "MATRIX: tensor([[ 7,  8,  9],\n",
      "        [ 9, 10, 11]])\n",
      "MATRIX.ndim: 2\n",
      "torch.Size([2, 3])\n"
     ]
    }
   ],
   "source": [
    "MATRIX = torch.tensor([[7, 8, 9],\n",
    "                       [9, 10, 11]])\n",
    "print(\"------------------------------------\")\n",
    "print(\"MATRIX:\", MATRIX)\n",
    "print(\"MATRIX.ndim:\", MATRIX.ndim)\n",
    "print(MATRIX.shape)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "b61d7e8b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "TENSOR: tensor([[[1, 2, 3],\n",
      "         [3, 6, 9],\n",
      "         [2, 4, 5]]])\n",
      "TENSOR.ndim: 3\n",
      "TENSOR.shape: torch.Size([1, 3, 3])\n"
     ]
    }
   ],
   "source": [
    "TENSOR = torch.tensor([[[1, 2, 3],\n",
    "                        [3, 6, 9],\n",
    "                        [2, 4, 5]]])\n",
    "print(\"------------------------------------\")\n",
    "print(\"TENSOR:\", TENSOR)\n",
    "print(\"TENSOR.ndim:\", TENSOR.ndim)\n",
    "print(\"TENSOR.shape:\", TENSOR.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8264cd98",
   "metadata": {},
   "source": [
    "#### 创建随机张量 `torch.rand(size)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "66b4e590",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "RANDOM:\n",
      "\n",
      "tensor([[0.1685, 0.0841, 0.2782, 0.1084],\n",
      "        [0.3056, 0.1100, 0.8260, 0.2210],\n",
      "        [0.8470, 0.7533, 0.3264, 0.3926]])\n",
      "random_tensor.ndim: 2\n",
      "random_tensor.shape: torch.Size([3, 4])\n"
     ]
    }
   ],
   "source": [
    "random_tensor = torch.rand(3, 4)\n",
    "print(\"------------------------------------\")\n",
    "print(\"RANDOM:\\n\")\n",
    "print(random_tensor)\n",
    "print(\"random_tensor.ndim:\", random_tensor.ndim)\n",
    "print(\"random_tensor.shape:\", random_tensor.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69bf0e80",
   "metadata": {},
   "source": [
    "#### 创建一个模仿一张图像的张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "30e7ac04",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "random_image_size_tensor:\n",
      " tensor([[[0.2492, 0.1643, 0.6649],\n",
      "         [0.2735, 0.4474, 0.6071],\n",
      "         [0.4013, 0.7809, 0.6290],\n",
      "         ...,\n",
      "         [0.3611, 0.1513, 0.4562],\n",
      "         [0.7076, 0.2147, 0.3680],\n",
      "         [0.8543, 0.2925, 0.1682]],\n",
      "\n",
      "        [[0.5954, 0.8361, 0.0569],\n",
      "         [0.4702, 0.8187, 0.3191],\n",
      "         [0.9371, 0.4380, 0.3739],\n",
      "         ...,\n",
      "         [0.0199, 0.9498, 0.6363],\n",
      "         [0.5419, 0.8659, 0.1758],\n",
      "         [0.3917, 0.3280, 0.6145]],\n",
      "\n",
      "        [[0.6278, 0.2548, 0.9042],\n",
      "         [0.8510, 0.1287, 0.3901],\n",
      "         [0.5523, 0.6982, 0.2659],\n",
      "         ...,\n",
      "         [0.1137, 0.9812, 0.7872],\n",
      "         [0.1887, 0.1542, 0.3325],\n",
      "         [0.7090, 0.2496, 0.8170]],\n",
      "\n",
      "        ...,\n",
      "\n",
      "        [[0.3511, 0.1280, 0.0377],\n",
      "         [0.9535, 0.2939, 0.9186],\n",
      "         [0.9604, 0.0503, 0.4280],\n",
      "         ...,\n",
      "         [0.6542, 0.1535, 0.6153],\n",
      "         [0.8843, 0.7794, 0.2544],\n",
      "         [0.8132, 0.5044, 0.9412]],\n",
      "\n",
      "        [[0.6913, 0.7114, 0.7625],\n",
      "         [0.4525, 0.3521, 0.5782],\n",
      "         [0.2928, 0.6778, 0.4968],\n",
      "         ...,\n",
      "         [0.9204, 0.1424, 0.6538],\n",
      "         [0.1694, 0.2449, 0.7111],\n",
      "         [0.8501, 0.7083, 0.6931]],\n",
      "\n",
      "        [[0.9387, 0.8331, 0.8991],\n",
      "         [0.8459, 0.9682, 0.6191],\n",
      "         [0.3536, 0.9420, 0.6176],\n",
      "         ...,\n",
      "         [0.5884, 0.8269, 0.8681],\n",
      "         [0.9652, 0.8573, 0.1568],\n",
      "         [0.3444, 0.2279, 0.5550]]])\n",
      "random_image_size_tensor.shape: torch.Size([224, 224, 3])\n",
      "random_image_size_tensor.dtype: torch.float32\n",
      "random_image_size_tensor.ndim: 3\n"
     ]
    }
   ],
   "source": [
    "random_image_size_tensor = torch.rand(size=(224, 224, 3))\n",
    "print(\"------------------------------------\")\n",
    "print(\"random_image_size_tensor:\\n\", random_image_size_tensor)\n",
    "print(\"random_image_size_tensor.shape:\", random_image_size_tensor.shape)\n",
    "print(\"random_image_size_tensor.dtype:\", random_image_size_tensor.dtype)\n",
    "print(\"random_image_size_tensor.ndim:\", random_image_size_tensor.ndim)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fd8acc3b",
   "metadata": {},
   "source": [
    "#### 创建全 0 或者 全 1 的张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "6b5af0ce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "zeros:\n",
      "tensor([[0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0.]])\n",
      "zeros.shape: torch.Size([3, 4])\n"
     ]
    }
   ],
   "source": [
    "zeros = torch.zeros(size=(3, 4))\n",
    "print(\"------------------------------------\")\n",
    "print(\"zeros:\")\n",
    "print(zeros)\n",
    "print(\"zeros.shape:\", zeros.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "10282bd8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "ones:\n",
      "tensor([[1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1.],\n",
      "        [1., 1., 1., 1.]])\n",
      "ones.shape: torch.Size([3, 4])\n",
      "ones.dtype: torch.float32\n"
     ]
    }
   ],
   "source": [
    "ones = torch.ones(size=(3, 4))\n",
    "print(\"------------------------------------\")\n",
    "print(\"ones:\")\n",
    "print(ones)\n",
    "print(\"ones.shape:\", ones.shape)\n",
    "print(\"ones.dtype:\", ones.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8fd7a12a",
   "metadata": {},
   "source": [
    "#### 创建一个范围的张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "545116d0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "zero_to_thousand:\n",
      "tensor([  0,  77, 154, 231, 308, 385, 462, 539, 616, 693, 770, 847, 924])\n",
      "zero_to_thousand.shape: torch.Size([13])\n"
     ]
    }
   ],
   "source": [
    "zero_to_thousand = torch.arange(start=0, end=1000, step=77)\n",
    "print(\"------------------------------------\")\n",
    "print(\"zero_to_thousand:\")\n",
    "print(zero_to_thousand)\n",
    "print(\"zero_to_thousand.shape:\", zero_to_thousand.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "77c238dd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "thousand_zeros:\n",
      "tensor([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])\n",
      "thousand_zeros.shape: torch.Size([13])\n"
     ]
    }
   ],
   "source": [
    "thousand_zeros = torch.zeros_like(input=zero_to_thousand)\n",
    "print(\"------------------------------------\")\n",
    "print(\"thousand_zeros:\")\n",
    "print(thousand_zeros)\n",
    "print(\"thousand_zeros.shape:\", thousand_zeros.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0e225340",
   "metadata": {},
   "source": [
    "#### 数据类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "b5237807",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "------------------------------------\n",
      "float_32_tensor:\n",
      "tensor([3., 6., 9.])\n",
      "float_32_tensor.dtype: torch.float32\n"
     ]
    }
   ],
   "source": [
    "float_32_tensor = torch.tensor([3.0, 6.0, 9.0],\n",
    "                               dtype=None, # 默认数据类型为 float32\n",
    "                               device=None,\n",
    "                               requires_grad=False) # 是否要跟踪张量操作的梯度\n",
    "print(\"------------------------------------\")\n",
    "print(\"float_32_tensor:\")\n",
    "print(float_32_tensor)\n",
    "print(\"float_32_tensor.dtype:\", float_32_tensor.dtype)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "71e377b0",
   "metadata": {},
   "source": [
    "**Note**: 张量常见的三种错误\n",
    "1. 张量数据类型错误\n",
    "2. 张量形状错误\n",
    "3. 张量在不同设备上的操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "75f24a10",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([3., 6., 9.], dtype=torch.float16)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float_16_tensor = float_32_tensor.type(torch.float16)\n",
    "float_16_tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "3a25e6b2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 9., 36., 81.])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float_16_tensor * float_32_tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "71148ee2",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([3, 6, 9])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "int_32_tensor = torch.tensor([3, 6, 9], dtype=torch.long)\n",
    "int_32_tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "701590da",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 9., 36., 81.])"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "float_32_tensor * int_32_tensor"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ea6d7959",
   "metadata": {},
   "source": [
    "#### 获取对应张量信息\n",
    "1. `tensor.dtype` 返回张量的数据类型\n",
    "2. `tensor.shape` 返回张量的形状\n",
    "3. `tensor.device` 返回张量所在的设备\n",
    "4. `tensor.requires_grad` 返回张量是否需要梯度\n",
    "5. `tensor.grad` 返回张量的梯度\n",
    "6. `tensor.grad_fn` 返回张量的梯度函数\n",
    "7. `tensor.is_leaf` 返回张量是否为叶子节点\n",
    "8. `tensor.grad.zero_()` 将张量的梯度清零\n",
    "9. `tensor.detach()` 将张量从计算图中分离出来\n",
    "10. `tensor.item()` 将张量转换为标量\n",
    "11. `tensor.view()` 将张量的形状改变\n",
    "12. `tensor.reshape()` 将张量的形状改变\n",
    "13. `tensor.permute()` 将张量的维度顺序改变\n",
    "14. `tensor.squeeze()` 将张量的维度压缩\n",
    "15. `tensor.unsqueeze()` 将张量的维度扩展\n",
    "16. `tensor.flatten()` 将张量展平\n",
    "17. `tensor.contiguous()` 将张量的内存布局调整为连续的\n",
    "18. `tensor.cpu()` 将张量移动到CPU上\n",
    "19. `tensor.cuda()` 将张量移动到GPU上\n",
    "20. `tensor.numpy()` 将张量转换为NumPy数组\n",
    "21. `tensor.from_numpy()` 将NumPy数组转换为张量\n",
    "22. `tensor.clone()` 将张量复制一份\n",
    "23. `tensor.register_hook()` 注册一个钩子函数\n",
    "24. `tensor.register_buffer()` 注册一个缓冲区\n",
    "25. `tensor.register_parameter()` 注册一个参数\n",
    "26. `tensor.register_forward_hook()` 注册一个前向钩子函数\n",
    "27. `tensor.register_backward_hook()` 注册一个反向钩子函数\n",
    "28. `tensor.register_forward_pre_hook()` 注册一个前向前钩子函数\n",
    "29. `tensor.register_forward_pre_hook()` 注册一个前向后钩子函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "39a732a3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.2202, 0.2297, 0.0344, 0.8327],\n",
       "        [0.4703, 0.2187, 0.1204, 0.6416],\n",
       "        [0.6328, 0.8712, 0.4259, 0.8522]])"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "some_tensor = torch.rand(3, 4)\n",
    "some_tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b9565e5d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Datatype of tensor: torch.float32\n",
      "Shape of tensor: torch.Size([3, 4])\n",
      "Device tensor is on: cpu\n"
     ]
    }
   ],
   "source": [
    "print(f\"Datatype of tensor: {some_tensor.dtype}\")\n",
    "print(f\"Shape of tensor: {some_tensor.shape}\")\n",
    "print(f\"Device tensor is on: {some_tensor.device}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f04941cb",
   "metadata": {},
   "source": [
    "### 张量运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "cb699b19",
   "metadata": {},
   "outputs": [],
   "source": [
    "tensor = torch.tensor([1, 2, 3])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "026d6d8a",
   "metadata": {},
   "source": [
    "#### 加法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "daecd2ac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([101, 102, 103])\n",
      "tensor([101, 102, 103])\n"
     ]
    }
   ],
   "source": [
    "print(tensor + 100)\n",
    "print(torch.add(tensor, 100))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59d0bfb9",
   "metadata": {},
   "source": [
    "#### 乘法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "c9eb589e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([10, 20, 30])\n",
      "tensor([10, 20, 30])\n"
     ]
    }
   ],
   "source": [
    "print(tensor * 10)\n",
    "print(torch.mul(tensor, 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4cc61a47",
   "metadata": {},
   "source": [
    "#### 减法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "708d476c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([-9, -8, -7])\n",
      "tensor([-9, -8, -7])\n"
     ]
    }
   ],
   "source": [
    "print(tensor - 10)\n",
    "print(torch.sub(tensor, 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a813103",
   "metadata": {},
   "source": [
    "#### 除法"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "e1667fb6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([0.1000, 0.2000, 0.3000])\n",
      "tensor([0.1000, 0.2000, 0.3000])\n"
     ]
    }
   ],
   "source": [
    "print(tensor / 10)\n",
    "print(torch.divide(tensor, 10))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cbae6a10",
   "metadata": {},
   "source": [
    "#### 矩阵乘法/点积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "9a72b3d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1, 2, 3]) * tensor([1, 2, 3])\n",
      "Equals: tensor([1, 4, 9])\n"
     ]
    }
   ],
   "source": [
    "print(tensor, \"*\", tensor)\n",
    "print(f\"Equals: {tensor * tensor}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "699d6f74",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1, 4, 9])\n",
      "tensor(14)\n"
     ]
    }
   ],
   "source": [
    "print(torch.mul(tensor, tensor))\n",
    "print(torch.matmul(tensor, tensor))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "781ced2e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(14)\n"
     ]
    }
   ],
   "source": [
    "value = 0\n",
    "for i in range(len(tensor)):\n",
    "    value += tensor[i] * tensor[i]\n",
    "print(value)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "3aeaae56",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[0.8675, 1.5529, 0.8998, 0.3923, 0.8197],\n",
       "        [1.6060, 2.0948, 1.1579, 0.5115, 1.2560],\n",
       "        [0.4035, 0.5444, 0.2782, 0.1180, 0.3343]])"
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.matmul(torch.rand(3, 4), torch.rand(4, 5))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e475f0be",
   "metadata": {},
   "source": [
    "#### 矩阵的转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "33169fb3",
   "metadata": {},
   "outputs": [],
   "source": [
    "tensor_A = torch.tensor([[1, 2],\n",
    "                         [3, 4],\n",
    "                         [5, 6]])\n",
    "\n",
    "tensor_B = torch.tensor([[7, 10],\n",
    "                         [8, 11],\n",
    "                         [9, 12]])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "c5039bad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 7,  8,  9],\n",
      "        [10, 11, 12]])\n"
     ]
    }
   ],
   "source": [
    "tensor_B = tensor_B.T\n",
    "print(tensor_B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "44079e3e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[ 27,  30,  33],\n",
       "        [ 61,  68,  75],\n",
       "        [ 95, 106, 117]])"
      ]
     },
     "execution_count": 32,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.mm(tensor_A, tensor_B)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "51acc3fa",
   "metadata": {},
   "source": [
    "### 张量聚合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "5fb85e64",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([ 1, 11, 21, 31, 41, 51, 61, 71, 81, 91])"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x = torch.arange(1, 100, 10)\n",
    "x"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "634577fd",
   "metadata": {},
   "source": [
    "#### 最小值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "5f61fe40",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(1) tensor(1)\n",
      "1 1\n",
      "tensor(0)\n"
     ]
    }
   ],
   "source": [
    "print(torch.min(x), x.min())\n",
    "print(torch.min(x).item(), x.min().item())\n",
    "print(x.argmin())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86696b43",
   "metadata": {},
   "source": [
    "#### 最大值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "a6dbf6d5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor(91) tensor(91)\n",
      "91 91\n",
      "tensor(9)\n",
      "tensor(91)\n"
     ]
    }
   ],
   "source": [
    "print(torch.max(x), x.max())\n",
    "print(torch.max(x).item(), x.max().item())\n",
    "print(x.argmax())\n",
    "print(x[x.argmax()])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a85dfa11",
   "metadata": {},
   "source": [
    "#### 平均值\n",
    "张量求平均值需要数据类型为 `float32`。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "b1d18f5c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor(46.), tensor(46.))"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.mean(x.type(torch.float32)), x.type(torch.float32).mean()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2ee2d5c",
   "metadata": {},
   "source": [
    "#### 求和"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "962521bd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor(460), tensor(460))"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "torch.sum(x), x.sum()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "65c6008e",
   "metadata": {},
   "source": [
    "---"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "2ef5d352",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.]),\n",
       " torch.Size([12]))"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "x = torch.arange(1.0, 13.0)\n",
    "x, x.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "016678a8",
   "metadata": {},
   "source": [
    "#### 重新塑性"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "1bf1cf89",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.]),\n",
       " torch.Size([12]))"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x_reshaped = x.reshape(12)\n",
    "x_reshaped, x_reshaped.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "987d6368",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.]])\n",
      "torch.Size([1, 12])\n"
     ]
    }
   ],
   "source": [
    "# Change the view, view 方法获得的张量与原张量共享内存，即一个改变，另一个也会改变\n",
    "z = x.view(1, 12)\n",
    "print(z)\n",
    "print(z.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "201ce739",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[ 1.,  2.,  5.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.]]),\n",
       " tensor([ 1.,  2.,  5.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11., 12.]),\n",
       " torch.Size([1, 12]))"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "z[0, 2] = 5 \n",
    "z , x, z.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f0c1724e",
   "metadata": {},
   "source": [
    "#### 堆叠"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "16499b2a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[ 1.,  1.,  1.,  1.],\n",
      "        [ 2.,  2.,  2.,  2.],\n",
      "        [ 5.,  5.,  5.,  5.],\n",
      "        [ 4.,  4.,  4.,  4.],\n",
      "        [ 5.,  5.,  5.,  5.],\n",
      "        [ 6.,  6.,  6.,  6.],\n",
      "        [ 7.,  7.,  7.,  7.],\n",
      "        [ 8.,  8.,  8.,  8.],\n",
      "        [ 9.,  9.,  9.,  9.],\n",
      "        [10., 10., 10., 10.],\n",
      "        [11., 11., 11., 11.],\n",
      "        [12., 12., 12., 12.]])\n",
      "torch.Size([12, 4])\n"
     ]
    }
   ],
   "source": [
    "x_stacked = torch.stack([x,x,x,x], dim=1)\n",
    "print(x_stacked)\n",
    "print(x_stacked.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7891d8b7",
   "metadata": {},
   "source": [
    "#### 挤压\n",
    "删除无效维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "id": "2d22f23b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[[[[0., 0.]],\n",
      "\n",
      "          [[0., 0.]]]],\n",
      "\n",
      "\n",
      "\n",
      "        [[[[0., 0.]],\n",
      "\n",
      "          [[0., 0.]]]]]) torch.Size([2, 1, 2, 1, 2])\n",
      "---------------------------------------\n",
      "tensor([[[0., 0.],\n",
      "         [0., 0.]],\n",
      "\n",
      "        [[0., 0.],\n",
      "         [0., 0.]]]) torch.Size([2, 2, 2])\n"
     ]
    }
   ],
   "source": [
    "# torch.squeeze() -removes all single dimensions from a target tensor\n",
    "x = torch.zeros(2, 1, 2, 1, 2)\n",
    "print(x, x.size())\n",
    "\n",
    "\n",
    "\n",
    "y = torch.squeeze(x)\n",
    "print(\"---------------------------------------\")\n",
    "print(y, y.size())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32165ad2",
   "metadata": {},
   "source": [
    "#### 展开\n",
    "`torch.unsqueeze(input, dim)` - 在指定维度上增加一个维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "737b1ac3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Previous target shape: torch.Size([1, 12, 4])\n",
      "tensor([[[ 1.,  1.,  1.,  1.],\n",
      "         [ 2.,  2.,  2.,  2.],\n",
      "         [ 5.,  5.,  5.,  5.],\n",
      "         [ 4.,  4.,  4.,  4.],\n",
      "         [ 5.,  5.,  5.,  5.],\n",
      "         [ 6.,  6.,  6.,  6.],\n",
      "         [ 7.,  7.,  7.,  7.],\n",
      "         [ 8.,  8.,  8.,  8.],\n",
      "         [ 9.,  9.,  9.,  9.],\n",
      "         [10., 10., 10., 10.],\n",
      "         [11., 11., 11., 11.],\n",
      "         [12., 12., 12., 12.]]])\n"
     ]
    }
   ],
   "source": [
    "x_unsqueezed = x_stacked.unsqueeze(dim=0)\n",
    "print(f\"Previous target shape: {x_unsqueezed.shape}\")\n",
    "print(x_unsqueezed)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6b6b4841",
   "metadata": {},
   "source": [
    "`torch.permute` - 重新排列维度，返回一个新的张量，不改变原张量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "e39cfb3f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([3, 224, 224])\n"
     ]
    }
   ],
   "source": [
    "x_original = torch.rand(size=(224, 224, 3))\n",
    "new_x = x_original.permute(2, 0, 1)\n",
    "print(new_x.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d928e235",
   "metadata": {},
   "source": [
    "### Indexing (selecting data from tensors)\n",
    "Indexing with PyTorch is similar to indexing with NumPy.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "c9823fec",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor([[[1, 2, 3],\n",
       "         [4, 5, 6],\n",
       "         [7, 8, 9]]])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import  torch\n",
    "x = torch.arange(1, 10).reshape(1, 3, 3)\n",
    "x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "499a2a6d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tensor(3)"
      ]
     },
     "execution_count": 47,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[0][0][2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "8ede3484",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([[2, 5, 8]]), tensor([[3, 6, 9]]), tensor([1, 2, 3]), tensor([9]))"
      ]
     },
     "execution_count": 48,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "x[:, :, 1], x[:, :, 2], x[0, 0, :], x[:, 2, 2]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "95483d58",
   "metadata": {},
   "source": [
    "### Pytorch tensors and numpy arrays"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "10f99cd5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([1., 2., 3., 4., 5., 6., 7.]),\n",
       " tensor([1., 2., 3., 4., 5., 6., 7.], dtype=torch.float64))"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "import numpy as np\n",
    "\n",
    "array = np.arange(1.0, 8.0)\n",
    "tensor = torch.from_numpy(array)\n",
    "array, tensor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "cfe70d26",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dtype('float64')"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# numpy 默认 数据类型是 float64,\n",
    "# 而 pytorch 默认 数据类型是 float32\n",
    "# 在 numpy 和 torch 互相转换时会 继承被转换前的数据类型\n",
    "array.dtype"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2d275282",
   "metadata": {},
   "source": [
    "### 创建随机但可复制的种子"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "96ba767d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([[0.8823, 0.9150, 0.3829, 0.9593],\n",
      "        [0.3904, 0.6009, 0.2566, 0.7936],\n",
      "        [0.9408, 0.1332, 0.9346, 0.5936]])\n",
      "tensor([[0.8823, 0.9150, 0.3829, 0.9593],\n",
      "        [0.3904, 0.6009, 0.2566, 0.7936],\n",
      "        [0.9408, 0.1332, 0.9346, 0.5936]])\n",
      "tensor([[True, True, True, True],\n",
      "        [True, True, True, True],\n",
      "        [True, True, True, True]])\n"
     ]
    }
   ],
   "source": [
    "import torch\n",
    "\n",
    "RANDOM_SEED = 42\n",
    "\n",
    "torch.manual_seed(RANDOM_SEED)\n",
    "random_tensor_A = torch.rand(3, 4)\n",
    "\n",
    "torch.manual_seed(RANDOM_SEED)\n",
    "random_tensor_B = torch.rand(3, 4)\n",
    "\n",
    "print(random_tensor_A)\n",
    "print(random_tensor_B)\n",
    "print(random_tensor_A == random_tensor_B)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ed0f9181",
   "metadata": {},
   "source": [
    "### 张量在不同设备上运行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "ee8743cb",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import torch\n",
    "torch.cuda.is_available()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "772020ae",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'cuda'"
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n",
    "device"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "e33e86be",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Count number of devices\n",
    "torch.cuda.device_count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "e01d0fc2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tensor([1, 2, 3]) cpu\n"
     ]
    }
   ],
   "source": [
    "tensor = torch.tensor([1, 2, 3])\n",
    "print(tensor, tensor.device)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "3b3a2a0e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(tensor([1, 2, 3], device='cuda:0'), device(type='cuda', index=0))"
      ]
     },
     "execution_count": 56,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Move tensor to GPU (if available)\n",
    "tensor_on_gpu = tensor.to(device)\n",
    "tensor_on_gpu, tensor_on_gpu.device"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2330dcb7",
   "metadata": {},
   "source": [
    "如过 张量在 GPU 上，则无法 将其转换为 NumPy 数组。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "env_isaaclab",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
